#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"

#include "php_ini.h"
#include "php_hello.h"
ZEND_DECLARE_MODULE_GLOBALS(hello)
static zend_function_entry hello_functions[] = {
	PHP_FE(hello_world, NULL)
	PHP_FE(hello_long, NULL)
	PHP_FE(hello_double, NULL)
	PHP_FE(hello_bool, NULL)
	PHP_FE(hello_null, NULL)
	ZEND_FE(sample_long,NULL)
	//ZEND_NAMED_FE(hi_long, ZEND_FN(sample_long), NULL)//函数别名,也可以写成PHP_NAMED_FE
	ZEND_FALIAS(hi_long, sample_long, NULL)//别名另一种写法
	{NULL, NULL, NULL}
};
zend_module_entry hello_module_entry = {
	#if ZEND_MODULE_API_NO >= 20010901
	STANDARD_MODULE_HEADER,
	#endif
	PHP_HELLO_WORLD_EXTNAME,
	hello_functions,
	PHP_MINIT(hello),
	PHP_RSHUTDOWN(hello),
	PHP_RINIT(hello),
	PHP_MSHUTDOWN(hello),
	NULL,
	#if ZEND_MODULE_API_NO >= 20010901
	PHP_HELLO_WORLD_VERSION,
	#endif
	STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_HELLO
ZEND_GET_MODULE(hello)
#endif
PHP_INI_BEGIN()
PHP_INI_ENTRY("hello.greeting", "Hello World",PHP_INI_ALL, NULL)
STD_PHP_INI_ENTRY("hello.direction", "1", PHP_INI_ALL,OnUpdateBool, direction, zend_hello_globals, hello_globals)
PHP_INI_END()
static void php_hello_init_globals(zend_hello_globals *hello_globals)
{
	hello_globals->direction = 1;
}

/*类定义*/
zend_class_entry *myclass_ce;
static zend_function_entry myclass_method[] = {
	ZEND_ME(myclass,    public_method,  NULL,   ZEND_ACC_PUBLIC)
    ZEND_ME(myclass,    __construct,    NULL,   ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
    { NULL, NULL, NULL }
};
/*接口定义*/
zend_class_entry *i_myinterface_ce;
static zend_function_entry i_myinterface_method[]={
    ZEND_ABSTRACT_ME(i_myinterface, hello, NULL) //注意这里的null指的是arginfo
    {NULL,NULL,NULL}
};

PHP_RINIT_FUNCTION(hello)
{
	HELLO_G(counter) = 0;
	return SUCCESS;
}

PHP_MINIT_FUNCTION(hello)
{
	//REGISTER_LONG_CONSTANT("SORT_REGULAR", PHP_SORT_REGULAR, CONST_CS | CONST_PERSISTENT);
	ZEND_INIT_MODULE_GLOBALS(hello, php_hello_init_globals,NULL);
	REGISTER_INI_ENTRIES();
	/*类的定义*/
	zend_class_entry ce;
    INIT_CLASS_ENTRY(ce,"myclass",myclass_method);
    myclass_ce =zend_register_internal_class(&ce TSRMLS_CC);

	//定义myclass类的属性
	zend_declare_property_null(myclass_ce,"public_var",strlen("public_var"), ZEND_ACC_PUBLIC TSRMLS_CC);
	
	/*接口定义*/
	zend_class_entry ice;
    INIT_CLASS_ENTRY(ice, "i_myinterface", i_myinterface_method);
    i_myinterface_ce = zend_register_internal_interface(&ice TSRMLS_CC);

	return SUCCESS;
	
}
PHP_MSHUTDOWN_FUNCTION(hello)
{
	UNREGISTER_INI_ENTRIES();
	return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(hello)
{
	return SUCCESS;
}

//首先，定义这个函数的C语言部分，不过这一次我们使用的是ZEND_METHOD
ZEND_METHOD( myclass , public_method )
{
    php_printf("我是public类型的方法\n");
}
 
ZEND_METHOD( myclass , __construct )
{
    php_printf("我是__construct方法\n");
}

PHP_FUNCTION(hello_world)
{
	RETURN_STRING("Hello World", 1);
}
PHP_FUNCTION(hello_long)
{
	if (HELLO_G(direction)) {
		HELLO_G(counter)++;
	} else {
		HELLO_G(counter)--;
	}
	RETURN_LONG(HELLO_G(counter));
}
PHP_FUNCTION(hello_double)
{
	RETURN_DOUBLE(3.1415926535);
}

PHP_FUNCTION(hello_bool)
{
	//数组操作
	//RETURN_BOOL(1);
	//array_init(return_value);
	/*
	zval *subarray;
	array_init(return_value);
	add_assoc_long(return_value,"life",42);
	add_index_bool(return_value,123,1);
	add_next_index_double(return_value,3.1415926535);
	
	add_next_index_string(return_value,"Foo",1);
	
	add_next_index_string(return_value,estrdup("Bar"),0);
	
	MAKE_STD_ZVAL(subarray);
	array_init(subarray);
	
	add_next_index_long(subarray,1);
	add_next_index_long(subarray,20);
	add_next_index_long(subarray,300);
	
	add_index_zval(return_value,444,subarray);
	*/
	/*
	zval *array;
	long sort_type = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
		RETURN_FALSE;
	}

	//php_set_compare_func(sort_type TSRMLS_CC);

	if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_reverse_key_compare, 0 TSRMLS_CC) == FAILURE) {
		RETURN_FALSE;
	}
	RETURN_TRUE;
	*/
}

PHP_FUNCTION(hello_null)
{
	//类的操作
	RETURN_NULL();
}


ZEND_FUNCTION(sample_long)
{
	//ZVAL_LONG(return_value, 42);
	//RETVAL_LONG(43);
	/*
	return_value_used  的使用
	if(return_value_used)
	{
		int i;
		//把返回值初始化成一个PHP语言中的数组
		array_init(return_value);
		for(i=0;i < 1000;i++)
		{
			//向retrun_value里不断的添加新元素，值为i
			add_next_index_long(return_value,i);
		}
		return ;
	}else{
		//抛出一个E_NOTICE级错误
        php_error_docref(NULL TSRMLS_CC, E_NOTICE,"猫了个咪的，我就知道你没用我的劳动成果！");
        RETURN_NULL();
	}
	*/
	
	/*
	以引用的形式返回值
	zval **a_ptr;
	zval *a;
	if(zend_hash_find(&EG(symbol_table),"a",sizeof("a"),(void **)&a_ptr ) == SUCCESS)
	{
		a= *a_ptr;
	}else{
		ALLOC_INIT_ZVAL(a);
		zend_hash_add(&EG(symbol_table), "a", sizeof("a"), &a,sizeof(zval*), NULL);
	}
	zval_ptr_dtor(return_value_ptr);
	
	if( !a->is_ref__gc && a->refcount__gc > 1 )
    {
        zval *tmp;
        MAKE_STD_ZVAL(tmp);
        *tmp = *a;
        zval_copy_ctor(tmp);
        tmp->is_ref__gc = 0;
        tmp->refcount__gc = 1;
        zend_hash_update(&EG(symbol_table), "a", sizeof("a"), &tmp,sizeof(zval*), NULL);
        a = tmp;
    }
    a->is_ref__gc = 1;
    a->refcount__gc++;
    *return_value_ptr = a;
	*/
	/*
	运行时传递引用
	zval *a;
	//我们接收的参数传给zval *a;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a) == FAILURE)
    {
		RETURN_STRING("Hello World", 1);
        //RETURN_NULL();
    }
	//如果a不是以引用的方式传递的。
    if (!a->is_ref__gc)
    {
		RETURN_STRING("not yy", 1);
        //return;
    }
	
	//将a转成字符串
    convert_to_string(a);
     
    //更改数据
    ZVAL_STRING(a," (modified by ref!)",1);
    return;
	*/
	/*
	函数的参数
	long foo;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"l", &foo) == FAILURE)
    {
        RETURN_NULL();
    }
    php_printf("The integer value of the parameter is: %ld\n", foo);
    RETURN_TRUE;
	*/
	/*
	一个字符串参数传递
	char *name;
    int name_len;
 
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",&name, &name_len) == FAILURE)
    {
        RETURN_NULL();
    }
    php_printf("Hello ");
    PHPWRITE(name, name_len);
    php_printf("!\n");
	*/
	/*
	两个字符串参数传递
	char *name;
    int name_len;
    char *greeting;
    int greeting_len;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",&name, &name_len, &greeting, &greeting_len) == FAILURE) {
        RETURN_NULL();
    }
    php_printf("Hello ");
    PHPWRITE(greeting, greeting_len);
    php_printf(" ");
    PHPWRITE(name, name_len);
    php_printf("!\n");
	*/
	/*
	函数参数的默认值
	char *name;
    int name_len;
    char *greeting = "Mr./Mrs.";
    int greeting_len = sizeof("Mr./Mrs.") - 1;
 
 
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
      &name, &name_len, &greeting, &greeting_len) == FAILURE) {
        RETURN_NULL();
    }
    php_printf("Hello ");
    PHPWRITE(greeting, greeting_len);
    php_printf(" ");
    PHPWRITE(name, name_len);
    php_printf("!\n");
	*/
	/*
	传参数是null的
	zval *val;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z",&val) == FAILURE) {
        RETURN_NULL();
    }
    if (Z_TYPE_P(val) == IS_NULL) {
        //val = php_sample_make_defaultval(TSRMLS_C);
		ZVAL_LONG(return_value, 42);
		return ;
    }
	ZVAL_LONG(return_value, 43);
	//php_printf("!\n");
	return ;
	*/
	/*
	不确定参数个数
	int i, argc = ZEND_NUM_ARGS();
    zval ***args;
 
    args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);
    if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE) {
        efree(args);
        WRONG_PARAM_COUNT;
    }
    for (i=0; i<argc; i++) {
        php_var_dump(args[i], 1 TSRMLS_CC);
    }
    efree(args);
	*/
	/*
	返回数组个数
	zval *arr;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a",&arr) == FAILURE)
    {
        RETURN_NULL();
    }
    RETURN_LONG(zend_hash_num_elements(Z_ARRVAL_P(arr)));
	*/
}

